#pragma once

#include "string"
#include "src/json.hpp"
#include "src/component/GuidGenerator.h"
#include "typeinfo"
#include "fmt/chrono.h"
#include "chrono"
#include "string_view"

template<typename T>
concept IsClass = std::is_class_v<T>;

template<IsClass T>
class Packet {
private:
    std::string Guid;
    std::string Source;
    std::string Destination;
    std::string Date;
    std::byte Flag;
    std::byte Status;
    std::string Type;
    std::byte Result;
    nlohmann::json Content;

public:
    Packet() = default;

    Packet(T value) {
        Guid = GuidGenerator::generateGuid();
        Source = "Client";
        Destination = "Client->Server";
        Date = fmt::format("{:%Y/%m/%d %H:%M:%S}",std::chrono::system_clock::now());
        Flag = std::byte(1);
        Status = std::byte(1);
        Type = typeid(value).name();
        //Result = result;
        Content = toJsonContent(value);
    };

    Packet(std::string_view receiveMessage) {
        nlohmann::json json = nlohmann::json::parse(receiveMessage);
        Guid = json.at("Guid");
        Source = json.at("Source");
        Destination = json.at("Destination");
        Date = json.at("Date");
        Flag = json.at("Flag");
        Status = json.at("Status");
        //Type = json.at("Type");
        Type = json.at("Type");
        Result = json.at("Result");
        Content = json.at("Content");
    };

    nlohmann::json toJson() {
        nlohmann::json json;
        json["Guid"] = Guid;
        json["Source"] = Source;
        json["Destination"] = Destination;
        json["Date"] = Date;
        json["Flag"] = Flag;
        json["Status"] = Status;
        json["Type"] = Type;
        json["Result"] = Result;
        json["Content"] = Content;
        return json;
    };

    static nlohmann::json toJsonContent(const T &value) {
        return {value};
    }

    static T fromJsonContent(const nlohmann::json &json) {
        return {json};
    }

    T fromJsonContent() {
        return {getContent()};
    }

    std::string toString() {
        return toJson().dump();
    };

    std::string getGuid() {
        return Guid;
    };

    std::string getSource() {
        return Source;
    };

    std::string getDestination() {
        return Destination;
    };

    std::string getDate() {
        return Date;
    };

    std::byte getFlag() {
        return Flag;
    };

    std::byte getStatus() {
        return Status;
    };

    std::string getType() {
        return Type;
    };

    std::byte getResult() {
        return Result;
    };

    nlohmann::json getContent() {
        return Content;
    };
};
